package org.shiro.action;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.shiro.bean.JsonResult;
import org.shiro.bean.PageBean;
import org.shiro.entity.Role;
import org.shiro.entity.User;
import org.shiro.entity.UserRole;
import org.shiro.groups.Group;
import org.shiro.service.RoleService;
import org.shiro.service.UserRoleService;
import org.shiro.service.UserService;
import org.shiro.util.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** @author LENOVO */
@Api(tags = "用户接口")
@RestController
@RequestMapping("/user")
public class UserController {
  @Autowired private UserService userService;
  @Autowired private UserRoleService userRoleService;
  @Autowired private RoleService roleService;

  @ApiOperation(value = "添加新用户")
  @PostMapping("/insert")
  @ResponseStatus(HttpStatus.CREATED)
  public JsonResult insertUser(@Validated(Group.GroupValidate.class)
      @RequestParam("username") String username,
      @RequestParam("password") String password,
      @RequestParam("file") MultipartFile file) {
    User user = new User();
    user.setUsername(username);
    String salt = new SecureRandomNumberGenerator().nextBytes().toHex();
    user.setSalt(salt);
    SimpleHash simpleHash = new SimpleHash(Md5Hash.ALGORITHM_NAME, password, salt, 5);
    user.setPassword(simpleHash.toHex());
    String url = FileUtils.uploadFile(file).getAbsolutePath();
    user.setUrl(url);
    int res = userService.create(user);
    if (res > 0) {
      return JsonResult.success("添加新用户成功", user);
    }
    return JsonResult.failure("添加新用户失败");
  }

  @ApiOperation(value = "用户登录")
  @PostMapping("/login")
  public JsonResult userLogin(
      @RequestParam("username") String username,
      @RequestParam("password") String password,
      HttpServletRequest request) {
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    token.setRememberMe(true);
    token.setHost("127.0.0.1");
    Subject subject = SecurityUtils.getSubject();
    try {
      subject.login(token);
      request.getSession().setAttribute("token", token);
    } catch (AuthenticationException e) {
      return JsonResult.failure("登陆失败，请重新登录");
    }
    return JsonResult.success("登陆成功", token);
  }

  @ApiOperation(value = "删除用户")
  @DeleteMapping("/{id}")
  public JsonResult deleteUser(@PathVariable("id") Long id) {
    int res = userService.remove(id);
    if (res > 0) {
      return JsonResult.success("删除数据成功");
    }
    return JsonResult.failure("删除数据失败");
  }

  @ApiOperation(value = "查找用户")
  @GetMapping("/{id}")
  public JsonResult loadUser(@PathVariable("id") Long id) {
    List<User> user = userService.load(id);
    if (user == null) {
      throw new IllegalArgumentException("该用户信息不在数据库中,请先添加用户数据");
    }
    return JsonResult.success("查询用户信息成功", user);
  }

  @ApiOperation(value = "更改用户信息")
  @PutMapping("/update")
  public JsonResult updateUser(@RequestBody User user) {
    int res = userService.modity(user);
    if (res > 0) {
      return JsonResult.success("更改用户信息成功", user);
    }
    return JsonResult.failure("更改用户信息失败");
  }

  @ApiOperation(value = "查询所有用户数据", notes = "按照提交数据从数据库中获取所有数据")
  @GetMapping("/queryAll")
  public JsonResult queryAll() {
    List<User> userList = userService.selectByAll();
    if (userList != null && userList.size() > 0) {
      return JsonResult.success("查询所有数据成功", userList);
    }
    return JsonResult.failure("查询所有数据失败");
  }

  @ApiOperation(value = "查询用户对应的角色")
  @GetMapping("/queryRole/")
  public JsonResult queryRole(@RequestParam("username") String username) {
    User user = userService.findUserByName(username);
    List<UserRole> userRoleList = userRoleService.queryByUserId(user.getId());
    if (userRoleList == null || userRoleList.size() < 0) {
      throw new IllegalArgumentException("表中没有数据，请先添加数据");
    }
    List<Role> roleList = roleService.selectByUserId(user.getId());
    if (roleList != null && roleList.size() > 0) {
      return JsonResult.success("查询数据成功", roleList);
    }
    return JsonResult.failure("查询数据失败");
  }

  @ApiOperation(value = "更改用户口令")
  @PutMapping("/updatePwd")
  public JsonResult changePassword(String username, String oldpassword, String newpassword) {
    int res = userService.changePassword(username, oldpassword, newpassword);
    if (res > 0) {
      return JsonResult.success("用户修改口令成功");
    }
    return JsonResult.failure("用户修改口令失败");
  }

  @ApiOperation(value = "更改用户头像")
  @PutMapping("/updateImg")
  @RequiresRoles(value = "Admin")
  @RequiresPermissions(value = "sys:user:update")
  public JsonResult changeImg(
      @RequestParam("file") MultipartFile file, @RequestParam("id") Long id) {
    int res = userService.changeImg(file, id);
    if (res <= 0) {
      throw new IllegalArgumentException("更换图像失败");
    }
    return JsonResult.success("更换图像成功");
  }

  @ApiOperation(value = "分页查询用户数据")
  @GetMapping("/page")
  public JsonResult selectByPage(@RequestParam("page") int page, @RequestParam("size") int size) {
    PageBean pageBean = new PageBean();
    pageBean.setPageNum(page);
    pageBean.setRowsPerPage(size);
    List<User> userList = userService.selectByPage(pageBean);
    pageBean.setRowsNum(userList.size());
    if (userList != null && userList.size() > 0) {
      return JsonResult.success("分页查询成功", userList);
    }
    return JsonResult.failure("分页查询失败");
  }

  @ApiOperation(value = "用户退出登录")
  @GetMapping("/logout")
  public void logout(HttpServletRequest request) {
    Subject subject = SecurityUtils.getSubject();
    try {
      subject.logout();
      request.getSession().removeAttribute("token");
    } catch (AuthenticationException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
  }

  @ApiOperation(value = "指定行数查找用户信息")
  @GetMapping("/pageByLimit")
  public JsonResult queryByLimit(
      @RequestParam("offset") int offset, @RequestParam("limit") int limit) {
    List<User> userList = userService.queryByLimit(offset, limit);
    if (userList == null || userList.size() <= 0) {
      throw new IllegalArgumentException("查找数据失败");
    }
    return JsonResult.success("查找数据成功", userList);
  }

  @ApiOperation(value = "用户无权访问")
  @GetMapping("/401")
  @ResponseStatus(HttpStatus.UNAUTHORIZED)
  public JsonResult Unauthorized(HttpServletRequest request) {
    String data = request.getAttribute("msg").toString();
    return JsonResult.success("当前用户无法访问该页面", data);
  }
}
